package com.cn.studemo.demos.web.service;


import com.cn.studemo.demos.web.mapper.UserMapper;
import com.cn.studemo.demos.web.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;

@Component
@Slf4j
public class MybatisBatchUtils {

    /**
     * 每次处理1000条
     */
    private static final int BATCH_SIZE = 3000;
    private static SqlSessionFactory sqlSessionFactory;
    @Autowired
    public   void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        MybatisBatchUtils.sqlSessionFactory = sqlSessionFactory;
    }

    public static   <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function) {
        int i = 1;
        long startTime = System.currentTimeMillis();
        log.info("开始时间 : {}", startTime);
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                function.apply(element,mapper);
                if ((i % BATCH_SIZE == 0) || i == size) {
                    batchSqlSession.flushStatements();
//                    batchSqlSession.commit();
//                    batchSqlSession.clearCache();
                }
                i++;
            }
            // 非事务环境下强制commit，事务情况下该commit相当于无效
            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception e) {
            batchSqlSession.rollback();
            throw new RuntimeException(e);
        } finally {
            batchSqlSession.close();
        }
        long endTime = System.currentTimeMillis();
        log.info("结束时间 : {}", startTime);
        log.info("BATCH_SIZE {}, 耗费时间 {}", BATCH_SIZE, (endTime - startTime));
        return i - 1;
    }








        public static void main(String[] args) {
            // 初始化数据
//            byte[] data = new byte[]{0x17, 0x00, 0x43, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            long l = System.currentTimeMillis();

            String hexString = "17 00 43 05 01 00 00 00 00 00 00 a7 e6 05 01 01 00 00 02 00 00";
            String hexStringFromB = hexString.replace(" ", "");


//            String hexString = "1700430501000000000000";
            byte[] data = toBytes(hexStringFromB.trim());

            // 计算CRC
            int crc = calculateCRC16X25(data);
            System.out.println("CRC = " + crc);
            // 将CRC转换为两个字节
//            byte[] crcBytes = new byte[]{(byte) ((crc >> 8) & 0xFF), (byte) (crc & 0xFF)};
            // 将CRC转换为两个字节, 并进行高低位互换，输出符合相关工具对Modbus CRC16的运算
            byte[] crcBytes = new byte[]{(byte) (crc & 0xFF),(byte) ((crc >> 8) & 0xFF)};
            // 输出结果
            System.out.printf("CRC-16/X.25: %02X%02X%n", crcBytes[0], crcBytes[1]);
            String hexString1 = toHexString1(crcBytes);
            System.out.println(hexString1);

            long currentTimeMillis = System.currentTimeMillis();
            System.out.println(currentTimeMillis - l);
            stopWatch.stop();
            System.out.println(stopWatch.getTotalTimeSeconds());
        }

    public static byte[] toBytes(String str) {  //  aa  -->  0xaa
        if (str == null || "".equals(str.trim())) {
            return new byte[0];
        }

        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }

        return bytes;
    }
    public static String toHexString1(byte[] b) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < b.length; ++i) {
            buffer.append(toHexString1(b[i]));
        }
        String str = buffer.toString().substring(0, buffer.length());
        return str;
    }
    public static String toHexString1(byte b) {
        String s = Integer.toHexString(b & 0xFF);
        if (s.length() == 1) {
            return "0" + s;
        } else {
            return s ;
        }
    }
        public static int calculateCRC16X25(byte[] data) {
            int crc = 0xFFFF; // 初始化CRC寄存器为0xFFFF

            for (byte b : data) {
                crc ^= (b & 0xFF); // 将数据字节的每个位与CRC寄存器的每个位进行异或操作

                for (int i = 0; i < 8; i++) {
                    if ((crc & 0x0001) != 0) {
                        crc >>= 1; // 将CRC寄存器右移一位
                        crc ^= 0x8408; // 与多项式0x8408进行异或操作
                    } else {
                        crc >>= 1; // 将CRC寄存器右移一位
                    }
                }
            }

            // 反转最终CRC值
            crc = ~crc;
            // 限制CRC值在16位范围内
            crc &= 0xFFFF;

            return crc;
        }







}
